package com.xxx.common.core.sampleframe.dao.impl;

import com.alibaba.fastjson.JSONObject;
import com.xxx.common.core.log.exception.BizException;
import com.xxx.common.core.sampleframe.SqlUtils;
import com.xxx.common.core.sampleframe.dao.FastDao;
import com.xxx.common.core.sampleframe.entity.BatchSql;
import com.xxx.common.core.sampleframe.search.Search;
import com.xxx.common.core.sampleframe.springside.Collections3;
import com.xxx.common.core.sampleframe.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class FastDaoImpl<T>   implements FastDao<T> {

	private Class<T> entityClass;
	@Autowired
	private JdbcTemplate jt;

	public FastDaoImpl() {
		Type genType = this.getClass().getGenericSuperclass();
		ParameterizedType type = (ParameterizedType) genType;
		Type[] params = type.getActualTypeArguments();
		entityClass = (Class) params[0];
	}


	@Override
	public void update(T t) {
		try {
			PreparedStatementCreator sql = SqlUtils.getUpdateSql(t);

			int i = jt.update(sql);
			if (i == 0) {
				throw BizException.DB_UPDATE_RESULT_0.newInstance("数据库操作,update返回0.{%s}", JSONObject.toJSONString(t));
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw BizException.DB_EERROR.newInstance("数据库操作错误{%s}", e.getMessage());
		}
	}

	@Override
	public void insert(T t) {
		KeyHolder keyHolder = new GeneratedKeyHolder();
		PreparedStatementCreator psc = null;
		try {
			psc = SqlUtils.getInsertPSC(t);
			int result = jt.update(psc, keyHolder);
			if (result == 0) {
				throw BizException.DB_INSERT_RESULT_0.newInstance("数据库操作,insert返回0.{%s}", JSONObject.toJSONString(t));
			}
			SqlUtils.filledGeneratedField(t, keyHolder);
		} catch (Exception e) {
			e.printStackTrace();
			throw BizException.DB_EERROR.newInstance("数据库操作错误{%s}", e.getMessage());
		}
	}

	@Override
	public void delete(T t) {
		try {
			String sql = SqlUtils.getDeleteSql(t);
			int result = jt.update(sql );
			if(result ==0){
				throw BizException.DB_DELETE_RESULT_0.newInstance("数据库操作,delete返回0,{%s}", sql);
			}

		} catch (Exception e) {
			e.printStackTrace();
			throw BizException.DB_DELETE_RESULT_0.newInstance("数据库操作错误{%s}", e.getMessage());
		}
	}

	@Override
	public void delete(Search search) {
		try {
			String sql = SqlUtils.getSearchDeleteSql(search, entityClass);
			int result = jt.update(sql);
			if(result ==0){
				throw BizException.DB_DELETE_RESULT_0.newInstance("数据库操作,delete返回0,{%s}", sql);
			}

		} catch (Exception e) {
			e.printStackTrace();
			throw BizException.DB_DELETE_RESULT_0.newInstance("数据库操作错误{%s}", e.getMessage());
		}
	}

	@Override
	public void delete(Long id) {
		 delete(new Search().addSearchFilter("EQ_id", id));
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> find(Search search) {
		String sql = null;
		try {
			SqlUtils.JPAInfo jpaInfo = SqlUtils.getJPAInfo(entityClass);
			sql = SqlUtils.getQuerySql(search, entityClass);
			return getTList(jt.query( sql, jpaInfo.getRowMapper()));
		}catch (Exception e){
			throw BizException.DB_SELECT_ERROR.newInstance("数据库查询错误{%s}{%s}",sql, e.getMessage());
		}
	}

	@Override
	public T findOne(Search search) {
		List<T> result = find(search);
		if (Collections3.isEmpty(result)) {
			return null;
		}
		return result.get(0);
	}

	@Override
	public T findById(Long id) {
		return findOne(new Search().addSearchFilter("EQ_id", id));
	}


	@SuppressWarnings("unchecked")
	@Override
	public Page<T> findPage(Search search) {

		Long count = count(search);
		String sql = null;
		try {
			SqlUtils.JPAInfo jpaInfo = SqlUtils.getJPAInfo(entityClass);
			sql = SqlUtils.getPageSql(search, entityClass);
			List<T> result = getTList(jt.query(SqlUtils.getPageSql(search, entityClass), jpaInfo.getRowMapper()));
			return new PageImpl<T>(result, search.getPageRequest(), count);
		}catch (Exception e){
			throw BizException.DB_PAGE_ERROR.newInstance("数据库查询 findpage方法错误{%s}{%s}",sql, e.getMessage());

		}

	}

	private List<T> getTList(List<Object> resultSet) {
		List<T> result = new ArrayList<T>();
		if (Collections3.isNotEmpty(resultSet)) {
			for (Object t : resultSet) {
				result.add((T) t);
			}
		}
		return result;
	}


	@Override
	public Long count(Search search) {
		String sql = null;
		try {
			sql = SqlUtils.getCountSql(search, entityClass);
			Long result = jt.queryForObject(sql, Long.class);
			return result;
		}catch (Exception e){
			throw BizException.DB_SELECT_ERROR.newInstance("数据库查询 count方法错误{%s}{%s}",sql, e.getMessage());
		}

	}

	@Override
	public void batchInsert(List<T> t) {
		BatchSql batchSql = null;
		try {
			batchSql = SqlUtils.getBatchInsertSql(t);
			int[] result  = jt.batchUpdate(batchSql.getSql(), batchSql.getBpss());
			for (int i :result) {
				if(i == 0){
					throw BizException.DB_BATCH_INSERT_RESULT_0.newInstance("数据库查询 批量插入错误}",batchSql.getSql());
				}
			}
		} catch (Exception e) {
			throw BizException.DB_BATCH_INSERT_RESULT_0.newInstance("数据库查询 批量插入错误{%s}{%s}",batchSql.getSql(), e.getMessage());
		}
	}

	@Override
	public List<T> findPageWithoutCount(Search search) {
		String sql = null;
		try {
			SqlUtils.JPAInfo jpaInfo = SqlUtils.getJPAInfo(entityClass);
			sql = SqlUtils.getPageSql(search, entityClass);
			List<T> result = getTList( jt.query(sql , jpaInfo.getRowMapper()));
			return result;
		}catch (Exception e){
			throw BizException.DB_PAGE_ERROR.newInstance("数据库查询 批量插入错误{%s}{%s}",sql, e.getMessage());
		}

	}


}